<script setup lang="ts">
import Grid from "@/components/framework/grid.vue";
import FolderPickerInput from "@/components/framework/folder-picker-input.vue";
import { useLocalShallowRef } from "@/framework/vue/hooks";
import { nextTick, onMounted, ref, shallowRef, watch } from "vue";
import path from "path-browserify-esm";
import { deleteFile, existsFile, readDir } from "@/framework/util/fs";
import { spawn } from "@/framework/util/cp";
import { message, Modal } from "ant-design-vue";
import ConfirmButton from "@/components/framework/confirm-button.vue";
import { useOnShow } from "@/components/framework/toggle-view-helper";
import type { ToolInstallVersionItem } from "@/pages/tools/common/types";
import { getVersionListFromNpmMirror } from "@/pages/tools/git/git-api";
import { VirtList } from "vue-virt-list";
import InstallerInstallOperation from "@/pages/tools/components/installer-install-operation.vue";
import { openExternal } from "@/framework/util/shell";

const installPath = useLocalShallowRef("git.install.path", "C:\\Program Files\\Git");
const installedVersion = ref<string>();
const versionLoading = ref(false);

watch(installPath, () => void nextTick(loadVersionInfo), { immediate: true });
useOnShow(() => void loadVersionInfo());

async function loadVersionInfo() {
  versionLoading.value = true;
  try {
    if (installPath.value) {
      const exeFile = path.join(installPath.value, "cmd\\git.exe");
      const exists = await existsFile(exeFile);
      if (exists) {
        const output = await spawn(exeFile, ["--version"]);
        const [, , ...omits] = output.trim().split(/\s/);
        installedVersion.value = omits.join("");
        return;
      }
    }
    installedVersion.value = undefined;
  } catch (e: any) {
    installedVersion.value = undefined;
    console.error(e);
    message.error(e.message);
  } finally {
    versionLoading.value = false;
  }
}

async function uninstall() {
  try {
    const files = await readDir(installPath.value);
    const uninstallFile = files.find(it => it.startsWith("unins") && it.endsWith(".exe"));
    if (!uninstallFile) {
      message.error("未找到Git for Windows的卸载文件");
      return;
    }
    openExternal(path.join(installPath.value, uninstallFile));
    Modal.confirm({
      centered: true,
      title: "安装",
      content: "已完成卸载？(在弹出的安装窗口手动安装完成后点击)",
      onOk: () => loadVersionInfo(),
    });
  } catch (e: any) {
    message.error(e.message);
    console.error(e);
  }
}

const downloadVersionList = shallowRef<ToolInstallVersionItem[]>([]);
const downloadVersionListLoading = ref(false);

async function loadDownloadVersionList() {
  downloadVersionListLoading.value = true;
  try {
    const list = await getVersionListFromNpmMirror();
    downloadVersionList.value = list;
    console.log(`[git] download version list`, list);
  } finally {
    downloadVersionListLoading.value = false;
  }
}

onMounted(() => void loadDownloadVersionList());

const getSavePath = (url: string) => path.join((proc.env.TMP || proc.env.TEMP) as string, "Denv", path.basename(url));

const onInstallCompleted = (e: ToolInstallVersionItem, localFile: string) => {
  deleteFile(localFile);
  loadVersionInfo();
};
</script>

<template>
  <div class="full-view git-manager">
    <grid rows-preset="two-rows-0">
      <div class="p-16 flex-sb child-flex-1 col-gap-16">
        <div class="flex aic">
          <span>安装路径：</span>
          <folder-picker-input v-model:value="installPath" :loading="versionLoading" class="flex-1" />
        </div>
        <div class="flex-sb col-gap-10">
          <template v-if="installedVersion">
            <span class="color-success">已安装，版本：{{ installedVersion }}</span>
            <a-space>
              <a-button @click="loadVersionInfo" :loading="versionLoading">刷新</a-button>
              <confirm-button danger content="确定卸载Git for Windows？" :confirm-cb="uninstall">卸载</confirm-button>
            </a-space>
          </template>
          <span v-else class="color-text-tertiary">未安装</span>
        </div>
      </div>

      <div>
        <virt-list :min-size="40" item-key="id" :list="downloadVersionList" class="border-top" item-class="tool-install-version-item">
          <template #default="{ itemData }">
            <div class="flex aic col-gap-10">
              <span style="min-width: 180px">{{ itemData.name }}</span>
              <span class="color-text-secondary">{{ itemData.modified?.toLocaleString() }}</span>
            </div>
            <installer-install-operation
              :id="itemData.id"
              :is-installed="itemData.name === installedVersion"
              :save-path="getSavePath(itemData.url)"
              :download-url="itemData.url"
              :install-callback="onInstallCompleted"
            />
          </template>
        </virt-list>
      </div>
    </grid>
  </div>
</template>
